package com.weiquan.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weiquan.dto.AdminCreateRequest;
import com.weiquan.dto.AdminLoginRequest;
import com.weiquan.dto.AdminUpdateRequest;
import com.weiquan.entity.SysAdmin;
import com.weiquan.exception.BusinessException;
import com.weiquan.mapper.SysAdminMapper;
import com.weiquan.service.SysAdminService;
import com.weiquan.utils.JwtUtils;
import com.weiquan.utils.RedisUtils;
import com.weiquan.vo.AdminInfoVO;
import com.weiquan.vo.AdminLoginResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 系统管理员服务实现类
 */
@Slf4j
@Service
public class SysAdminServiceImpl extends ServiceImpl<SysAdminMapper, SysAdmin> implements SysAdminService {

    @Autowired
    private SysAdminMapper adminMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private JwtUtils jwtUtils;

    // Redis键前缀
    private static final String ADMIN_TOKEN_PREFIX = "admin:token:";
    private static final String ADMIN_INFO_PREFIX = "admin:info:";
    private static final String ADMIN_PERMISSIONS_PREFIX = "admin:permissions:";

    // 角色映射
    private static final Map<Integer, String> ROLE_MAP = new HashMap<>();
    static {
        ROLE_MAP.put(1, "超级管理员");
        ROLE_MAP.put(2, "内容管理员");
        ROLE_MAP.put(3, "客服管理员");
    }

    // 状态映射
    private static final Map<Integer, String> STATUS_MAP = new HashMap<>();
    static {
        STATUS_MAP.put(0, "禁用");
        STATUS_MAP.put(1, "启用");
    }

    @Override
    public AdminLoginResponse login(AdminLoginRequest request, String clientIp) {
        // 查询管理员
        SysAdmin admin = adminMapper.selectByUsername(request.getUsername());
        if (admin == null) {
            throw new BusinessException("用户名或密码错误");
        }

        // 检查状态
        if (admin.getStatus() == 0) {
            throw new BusinessException("账号已被禁用，请联系超级管理员");
        }

        // 验证密码
        if (!passwordEncoder.matches(request.getPassword(), admin.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }

        // 生成Token
        String token = jwtUtils.generateToken(admin.getId().toString(), "admin");
        
        // 更新登录信息
        adminMapper.updateLastLoginInfo(admin.getId(), LocalDateTime.now(), clientIp);

        // 缓存Token和管理员信息
        long expireTime = request.getRememberMe() ? 7 * 24 * 60 * 60 : 24 * 60 * 60; // 记住我7天，否则1天
        redisUtils.set(ADMIN_TOKEN_PREFIX + token, admin.getId(), expireTime);
        redisUtils.set(ADMIN_INFO_PREFIX + admin.getId(), admin, expireTime);

        // 构建响应
        AdminLoginResponse response = new AdminLoginResponse();
        response.setAccessToken(token);
        response.setRefreshToken(token); // 简化处理，实际可以生成不同的刷新token
        response.setExpiresIn(expireTime);

        // 设置管理员信息
        AdminLoginResponse.AdminInfo adminInfo = new AdminLoginResponse.AdminInfo();
        adminInfo.setId(admin.getId());
        adminInfo.setUsername(admin.getUsername());
        adminInfo.setRealName(admin.getRealName());
        adminInfo.setAvatar(admin.getAvatar());
        adminInfo.setRole(admin.getRole());
        adminInfo.setRoleName(ROLE_MAP.get(admin.getRole()));
        adminInfo.setLastLoginTime(admin.getLastLoginTime());
        adminInfo.setLoginCount(admin.getLoginCount() + 1);

        // 设置权限
        if (StringUtils.hasText(admin.getPermissions())) {
            adminInfo.setPermissions(JSON.parseArray(admin.getPermissions(), String.class));
        } else {
            adminInfo.setPermissions(getDefaultPermissions(admin.getRole()));
        }

        response.setAdminInfo(adminInfo);

        log.info("管理员{}登录成功，IP：{}", admin.getUsername(), clientIp);
        
        return response;
    }

    @Override
    public boolean logout(String token) {
        try {
            // 从Redis中删除Token
            redisUtils.delete(ADMIN_TOKEN_PREFIX + token);
            
            // 可以记录登出日志
            log.info("管理员登出，Token：{}", token.substring(0, 10) + "...");
            
            return true;
        } catch (Exception e) {
            log.error("管理员登出失败", e);
            return false;
        }
    }

    @Override
    public AdminInfoVO getAdminInfo(Long adminId) {
        SysAdmin admin = adminMapper.selectById(adminId);
        if (admin == null || admin.getIsDeleted() == 1) {
            throw new BusinessException("管理员不存在");
        }

        return convertToVO(admin);
    }

    @Override
    @Transactional
    public boolean createAdmin(AdminCreateRequest request, Long createBy) {
        // 检查用户名是否存在
        if (checkUsernameExists(request.getUsername(), null)) {
            throw new BusinessException("用户名已存在");
        }

        // 检查手机号是否存在
        if (checkPhoneExists(request.getPhoneNumber(), null)) {
            throw new BusinessException("手机号已存在");
        }

        // 检查邮箱是否存在
        if (StringUtils.hasText(request.getEmail()) && checkEmailExists(request.getEmail(), null)) {
            throw new BusinessException("邮箱已存在");
        }

        // 创建管理员
        SysAdmin admin = new SysAdmin();
        BeanUtils.copyProperties(request, admin);
        
        // 加密密码
        admin.setPassword(passwordEncoder.encode(request.getPassword()));
        
        // 设置权限
        if (request.getPermissions() != null && !request.getPermissions().isEmpty()) {
            admin.setPermissions(JSON.toJSONString(request.getPermissions()));
        } else {
            admin.setPermissions(JSON.toJSONString(getDefaultPermissions(request.getRole())));
        }
        
        admin.setCreateBy(createBy);
        admin.setLoginCount(0);

        int result = adminMapper.insert(admin);
        
        if (result > 0) {
            log.info("创建管理员成功，用户名：{}，创建者：{}", request.getUsername(), createBy);
            return true;
        }
        
        return false;
    }

    @Override
    @Transactional
    public boolean updateAdmin(Long adminId, AdminUpdateRequest request, Long updateBy) {
        SysAdmin admin = adminMapper.selectById(adminId);
        if (admin == null || admin.getIsDeleted() == 1) {
            throw new BusinessException("管理员不存在");
        }

        // 检查手机号是否存在
        if (StringUtils.hasText(request.getPhoneNumber()) && 
            checkPhoneExists(request.getPhoneNumber(), adminId)) {
            throw new BusinessException("手机号已存在");
        }

        // 检查邮箱是否存在
        if (StringUtils.hasText(request.getEmail()) && 
            checkEmailExists(request.getEmail(), adminId)) {
            throw new BusinessException("邮箱已存在");
        }

        // 更新管理员信息
        if (StringUtils.hasText(request.getRealName())) {
            admin.setRealName(request.getRealName());
        }
        if (StringUtils.hasText(request.getPhoneNumber())) {
            admin.setPhoneNumber(request.getPhoneNumber());
        }
        if (StringUtils.hasText(request.getEmail())) {
            admin.setEmail(request.getEmail());
        }
        if (StringUtils.hasText(request.getAvatar())) {
            admin.setAvatar(request.getAvatar());
        }
        if (request.getRole() != null) {
            admin.setRole(request.getRole());
        }
        if (request.getPermissions() != null) {
            admin.setPermissions(JSON.toJSONString(request.getPermissions()));
        }
        if (request.getStatus() != null) {
            admin.setStatus(request.getStatus());
        }
        if (StringUtils.hasText(request.getRemark())) {
            admin.setRemark(request.getRemark());
        }
        
        admin.setUpdateBy(updateBy);

        int result = adminMapper.updateById(admin);
        
        if (result > 0) {
            // 清除缓存
            redisUtils.delete(ADMIN_INFO_PREFIX + adminId);
            
            log.info("更新管理员成功，ID：{}，更新者：{}", adminId, updateBy);
            return true;
        }
        
        return false;
    }

    @Override
    @Transactional
    public boolean deleteAdmin(Long adminId, Long deleteBy) {
        SysAdmin admin = adminMapper.selectById(adminId);
        if (admin == null || admin.getIsDeleted() == 1) {
            throw new BusinessException("管理员不存在");
        }

        // 不能删除自己
        if (adminId.equals(deleteBy)) {
            throw new BusinessException("不能删除自己");
        }

        // 软删除
        admin.setIsDeleted(1);
        admin.setUpdateBy(deleteBy);

        int result = adminMapper.updateById(admin);
        
        if (result > 0) {
            // 清除缓存
            redisUtils.delete(ADMIN_INFO_PREFIX + adminId);
            
            log.info("删除管理员成功，ID：{}，删除者：{}", adminId, deleteBy);
            return true;
        }
        
        return false;
    }

    @Override
    @Transactional
    public boolean batchDeleteAdmin(List<Long> adminIds, Long deleteBy) {
        // 移除自己的ID
        adminIds.remove(deleteBy);
        
        if (adminIds.isEmpty()) {
            throw new BusinessException("没有可删除的管理员");
        }

        // 批量软删除
        QueryWrapper<SysAdmin> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", adminIds);
        queryWrapper.eq("is_deleted", 0);

        SysAdmin updateAdmin = new SysAdmin();
        updateAdmin.setIsDeleted(1);
        updateAdmin.setUpdateBy(deleteBy);

        int result = adminMapper.update(updateAdmin, queryWrapper);
        
        if (result > 0) {
            // 清除缓存
            adminIds.forEach(id -> redisUtils.delete(ADMIN_INFO_PREFIX + id));
            
            log.info("批量删除管理员成功，数量：{}，删除者：{}", result, deleteBy);
            return true;
        }
        
        return false;
    }

    @Override
    public boolean updateAdminStatus(Long adminId, Integer status, Long updateBy) {
        SysAdmin admin = adminMapper.selectById(adminId);
        if (admin == null || admin.getIsDeleted() == 1) {
            throw new BusinessException("管理员不存在");
        }

        // 不能禁用自己
        if (adminId.equals(updateBy) && status == 0) {
            throw new BusinessException("不能禁用自己");
        }

        admin.setStatus(status);
        admin.setUpdateBy(updateBy);

        int result = adminMapper.updateById(admin);
        
        if (result > 0) {
            // 清除缓存
            redisUtils.delete(ADMIN_INFO_PREFIX + adminId);
            
            log.info("更新管理员状态成功，ID：{}，状态：{}，更新者：{}", adminId, status, updateBy);
            return true;
        }
        
        return false;
    }

    @Override
    public boolean batchUpdateAdminStatus(List<Long> adminIds, Integer status, Long updateBy) {
        // 如果是禁用操作，移除自己的ID
        if (status == 0) {
            adminIds.remove(updateBy);
        }
        
        if (adminIds.isEmpty()) {
            throw new BusinessException("没有可更新的管理员");
        }

        String ids = adminIds.stream().map(String::valueOf).collect(Collectors.joining(","));
        int result = adminMapper.batchUpdateStatus(ids, status);
        
        if (result > 0) {
            // 清除缓存
            adminIds.forEach(id -> redisUtils.delete(ADMIN_INFO_PREFIX + id));
            
            log.info("批量更新管理员状态成功，数量：{}，状态：{}，更新者：{}", result, status, updateBy);
            return true;
        }
        
        return false;
    }

    @Override
    public boolean resetPassword(Long adminId, String newPassword, Long updateBy) {
        SysAdmin admin = adminMapper.selectById(adminId);
        if (admin == null || admin.getIsDeleted() == 1) {
            throw new BusinessException("管理员不存在");
        }

        admin.setPassword(passwordEncoder.encode(newPassword));
        admin.setUpdateBy(updateBy);

        int result = adminMapper.updateById(admin);
        
        if (result > 0) {
            log.info("重置管理员密码成功，ID：{}，重置者：{}", adminId, updateBy);
            return true;
        }
        
        return false;
    }

    @Override
    public boolean changePassword(Long adminId, String oldPassword, String newPassword) {
        SysAdmin admin = adminMapper.selectById(adminId);
        if (admin == null || admin.getIsDeleted() == 1) {
            throw new BusinessException("管理员不存在");
        }

        // 验证旧密码
        if (!passwordEncoder.matches(oldPassword, admin.getPassword())) {
            throw new BusinessException("原密码错误");
        }

        admin.setPassword(passwordEncoder.encode(newPassword));

        int result = adminMapper.updateById(admin);
        
        if (result > 0) {
            log.info("管理员修改密码成功，ID：{}", adminId);
            return true;
        }
        
        return false;
    }

    @Override
    public Page<AdminInfoVO> getAdminList(int pageNum, int pageSize, String keyword, Integer role, Integer status) {
        Page<SysAdmin> page = new Page<>(pageNum, pageSize);
        
        QueryWrapper<SysAdmin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted", 0);
        
        if (StringUtils.hasText(keyword)) {
            queryWrapper.and(wrapper -> wrapper
                .like("username", keyword)
                .or().like("real_name", keyword)
                .or().like("phone_number", keyword)
                .or().like("email", keyword)
            );
        }
        
        if (role != null) {
            queryWrapper.eq("role", role);
        }
        
        if (status != null) {
            queryWrapper.eq("status", status);
        }
        
        queryWrapper.orderByDesc("create_time");
        
        Page<SysAdmin> adminPage = adminMapper.selectPage(page, queryWrapper);
        
        // 转换为VO
        Page<AdminInfoVO> voPage = new Page<>();
        BeanUtils.copyProperties(adminPage, voPage);
        
        List<AdminInfoVO> voList = adminPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
        
        voPage.setRecords(voList);
        
        return voPage;
    }

    @Override
    public List<AdminInfoVO> getAdminsByRole(Integer role) {
        List<SysAdmin> adminList = adminMapper.selectByRole(role);
        
        return adminList.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public boolean checkUsernameExists(String username, Long excludeId) {
        QueryWrapper<SysAdmin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        queryWrapper.eq("is_deleted", 0);
        
        if (excludeId != null) {
            queryWrapper.ne("id", excludeId);
        }
        
        return adminMapper.selectCount(queryWrapper) > 0;
    }

    @Override
    public boolean checkPhoneExists(String phoneNumber, Long excludeId) {
        QueryWrapper<SysAdmin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone_number", phoneNumber);
        queryWrapper.eq("is_deleted", 0);
        
        if (excludeId != null) {
            queryWrapper.ne("id", excludeId);
        }
        
        return adminMapper.selectCount(queryWrapper) > 0;
    }

    @Override
    public boolean checkEmailExists(String email, Long excludeId) {
        QueryWrapper<SysAdmin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email);
        queryWrapper.eq("is_deleted", 0);
        
        if (excludeId != null) {
            queryWrapper.ne("id", excludeId);
        }
        
        return adminMapper.selectCount(queryWrapper) > 0;
    }

    @Override
    public Map<String, Object> getAdminStatistics() {
        Map<String, Object> statistics = new HashMap<>();
        
        // 总数统计
        QueryWrapper<SysAdmin> totalWrapper = new QueryWrapper<>();
        totalWrapper.eq("is_deleted", 0);
        statistics.put("totalCount", adminMapper.selectCount(totalWrapper));
        
        // 启用数量
        QueryWrapper<SysAdmin> activeWrapper = new QueryWrapper<>();
        activeWrapper.eq("is_deleted", 0).eq("status", 1);
        statistics.put("activeCount", adminMapper.selectCount(activeWrapper));
        
        // 角色统计
        List<Map<String, Object>> roleStats = adminMapper.countByRole();
        statistics.put("roleStats", roleStats);
        
        // 今日登录数量
        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        QueryWrapper<SysAdmin> todayWrapper = new QueryWrapper<>();
        todayWrapper.eq("is_deleted", 0).ge("last_login_time", todayStart);
        statistics.put("todayLoginCount", adminMapper.selectCount(todayWrapper));
        
        return statistics;
    }

    @Override
    public List<Map<String, Object>> getLoginStatistics(String startDate, String endDate) {
        LocalDateTime start = LocalDateTime.parse(startDate + " 00:00:00", 
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime end = LocalDateTime.parse(endDate + " 23:59:59", 
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        
        return adminMapper.getLoginStatistics(start, end);
    }

    @Override
    public List<AdminInfoVO> getRecentLoginAdmins(int limit) {
        List<SysAdmin> adminList = adminMapper.selectRecentLogin(limit);
        
        return adminList.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public boolean hasPermission(Long adminId, String permission) {
        List<String> permissions = getAdminPermissions(adminId);
        return permissions.contains(permission) || permissions.contains("*");
    }

    @Override
    public boolean updatePermissions(Long adminId, List<String> permissions, Long updateBy) {
        SysAdmin admin = adminMapper.selectById(adminId);
        if (admin == null || admin.getIsDeleted() == 1) {
            throw new BusinessException("管理员不存在");
        }

        admin.setPermissions(JSON.toJSONString(permissions));
        admin.setUpdateBy(updateBy);

        int result = adminMapper.updateById(admin);
        
        if (result > 0) {
            // 清除权限缓存
            redisUtils.delete(ADMIN_PERMISSIONS_PREFIX + adminId);
            
            log.info("更新管理员权限成功，ID：{}，更新者：{}", adminId, updateBy);
            return true;
        }
        
        return false;
    }

    @Override
    public List<String> getAdminPermissions(Long adminId) {
        // 先从缓存获取
        String cacheKey = ADMIN_PERMISSIONS_PREFIX + adminId;
        List<String> cachedPermissions = (List<String>) redisUtils.get(cacheKey);
        if (cachedPermissions != null) {
            return cachedPermissions;
        }

        // 从数据库获取
        SysAdmin admin = adminMapper.selectById(adminId);
        if (admin == null || admin.getIsDeleted() == 1) {
            return new ArrayList<>();
        }

        List<String> permissions;
        if (StringUtils.hasText(admin.getPermissions())) {
            permissions = JSON.parseArray(admin.getPermissions(), String.class);
        } else {
            permissions = getDefaultPermissions(admin.getRole());
        }

        // 缓存权限
        redisUtils.set(cacheKey, permissions, 60 * 60); // 1小时
        
        return permissions;
    }

    @Override
    public String refreshToken(String oldToken) {
        Long adminId = (Long) redisUtils.get(ADMIN_TOKEN_PREFIX + oldToken);
        if (adminId == null) {
            throw new BusinessException("Token无效");
        }

        // 生成新Token
        String newToken = jwtUtils.generateToken(adminId.toString(), "admin");
        
        // 删除旧Token，保存新Token
        redisUtils.delete(ADMIN_TOKEN_PREFIX + oldToken);
        redisUtils.set(ADMIN_TOKEN_PREFIX + newToken, adminId, 24 * 60 * 60); // 1天
        
        return newToken;
    }

    @Override
    public SysAdmin validateToken(String token) {
        Long adminId = (Long) redisUtils.get(ADMIN_TOKEN_PREFIX + token);
        if (adminId == null) {
            return null;
        }

        // 先从缓存获取
        SysAdmin cachedAdmin = (SysAdmin) redisUtils.get(ADMIN_INFO_PREFIX + adminId);
        if (cachedAdmin != null) {
            return cachedAdmin;
        }

        // 从数据库获取
        SysAdmin admin = adminMapper.selectById(adminId);
        if (admin != null && admin.getIsDeleted() == 0 && admin.getStatus() == 1) {
            // 缓存管理员信息
            redisUtils.set(ADMIN_INFO_PREFIX + adminId, admin, 60 * 60); // 1小时
            return admin;
        }

        return null;
    }

    @Override
    public void recordOperationLog(Long adminId, String operation, String details, String clientIp) {
        // 这里可以实现操作日志记录
        log.info("管理员操作日志 - 管理员ID：{}，操作：{}，详情：{}，IP：{}", adminId, operation, details, clientIp);
    }

    /**
     * 转换为VO
     */
    private AdminInfoVO convertToVO(SysAdmin admin) {
        AdminInfoVO vo = new AdminInfoVO();
        BeanUtils.copyProperties(admin, vo);
        
        vo.setRoleName(ROLE_MAP.get(admin.getRole()));
        vo.setStatusName(STATUS_MAP.get(admin.getStatus()));
        
        // 解析权限
        if (StringUtils.hasText(admin.getPermissions())) {
            vo.setPermissions(JSON.parseArray(admin.getPermissions(), String.class));
        } else {
            vo.setPermissions(getDefaultPermissions(admin.getRole()));
        }
        
        // 检查是否在线（简化处理）
        vo.setOnline(redisUtils.hasKey(ADMIN_INFO_PREFIX + admin.getId()));
        
        return vo;
    }

    /**
     * 获取默认权限
     */
    private List<String> getDefaultPermissions(Integer role) {
        List<String> permissions = new ArrayList<>();
        
        switch (role) {
            case 1: // 超级管理员
                permissions.add("*"); // 所有权限
                break;
            case 2: // 内容管理员
                permissions.addAll(Arrays.asList(
                    "community:view", "community:edit", "community:delete",
                    "template:view", "template:edit", "template:delete",
                    "user:view"
                ));
                break;
            case 3: // 客服管理员
                permissions.addAll(Arrays.asList(
                    "user:view", "user:edit",
                    "community:view", "community:edit",
                    "ai:view"
                ));
                break;
            default:
                permissions.add("dashboard:view");
                break;
        }
        
        return permissions;
    }
}